﻿// (c) Norbert Huffschmid
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Threading;
using SpinDotters.Core;

namespace SpinDotters.Widgets
{
    /// <summary>
    /// Clock control
    /// </summary>
    public partial class Clock : SpinningControlContainer, INotifyPropertyChanged
    {
        private const bool HAS_SECONDS_DEFAULT = true;
        private const ClockTimeFormat TIME_FORMAT_DEFAULT = ClockTimeFormat.Automatic;


        public enum ClockTimeFormat
        {
            Automatic,
            TwelveHours,
            TwentyfourHours
        }


        /// <summary>
        /// Notifies listeners that a property value has changed.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;


        private DispatcherTimer timer = new DispatcherTimer();


        /// <summary>
        /// HasSeconds dependency property.
        /// </summary>
        public static readonly DependencyProperty HasSecondsProperty =
            DependencyProperty.Register(
                "HasSeconds",
                typeof(bool),
                typeof(Clock),
                new PropertyMetadata(HAS_SECONDS_DEFAULT, new PropertyChangedCallback(OnHasSecondsChanged))
                );

        /// <summary>
        /// Gets or sets the fact whether the clock shows seconds or not.
        /// </summary>
        [Category("SpinDotters")]
        public bool HasSeconds
        {
            get { return (bool)GetValue(HasSecondsProperty); }
            set { SetValue(HasSecondsProperty, value); }
        }

        /// <summary>
        /// TimeFormat dependency property.
        /// </summary>
        public static readonly DependencyProperty TimeFormatProperty =
            DependencyProperty.Register(
                "TimeFormat",
                typeof(ClockTimeFormat),
                typeof(Clock),
                new PropertyMetadata(TIME_FORMAT_DEFAULT, new PropertyChangedCallback(OnTimeFormatChanged)));

        /// <summary>
        /// Gets or sets the time format (24-hours, 12-hours or automatically determined by current culture)
        /// </summary>
        [Category("SpinDotters")]
        public virtual ClockTimeFormat TimeFormat
        {
            get { return (ClockTimeFormat)GetValue(TimeFormatProperty); }
            set { SetValue(TimeFormatProperty, value); }
        }


        public Clock()
        {
            this.DefaultStyleKey = typeof(Clock);

            timer.Interval = new TimeSpan(0, 0, 1);
            timer.Tick += new EventHandler(timer_Tick);

            this.Loaded += new RoutedEventHandler(Clock_Loaded);
            this.Unloaded += new RoutedEventHandler(Clock_Unloaded);

            this.DataContext = this;
        }


        protected virtual void OnPropertyChanged(String info)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(info));
        }


        private void timer_Tick(object sender, EventArgs e)
        {
            OnPropertyChanged("HoursHigh");
            OnPropertyChanged("HoursLow");
            OnPropertyChanged("MinutesHigh");
            OnPropertyChanged("MinutesLow");
            OnPropertyChanged("SecondsHigh");
            OnPropertyChanged("SecondsLow");
            OnPropertyChanged("AmPmIndex");
        }

        private void Clock_Loaded(object sender, RoutedEventArgs e)
        {
            timer.Start();
        }

        private void Clock_Unloaded(object sender, RoutedEventArgs e)
        {
            timer.Stop();
        }

        private static void OnHasSecondsChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            Clock clock = (Clock)dependencyObject;
            clock.OnPropertyChanged("SecondsVisibility");
        }

        private static void OnTimeFormatChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            Clock clock = (Clock)dependencyObject;
            clock.OnPropertyChanged("TimeFormat");
        }
    }
}
